﻿using Microsoft.Extensions.Logging;
using Simple.Framework.Ioc;
using Simple.Framework.Logger;
using Simple.SnowFlake;
using Simple.Tools;
using SimpleNet.Handle;
using SimpleNet.Net;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

/*********************************************************
 * 命名空间 Simple.BasicNet.Core.Net
 * 接口名称 Connection
 * 开发人员：11920
 * 创建时间：2023/4/25 9:39:51
 * 描述说明：
 * 更改历史：
 * 
 * *******************************************************/
namespace SimpleNet
{
	internal class Connection:IConnection
	{
		//private Stopwatch stopwatch;
		//private long time;
		public Connection(IContainer container)
		{
			this.container = container;
			sysCfg = container.GetService<SystemConfiguration>();
			clientManager = container.GetService<IClientManager>();
			logger = container.GetService<ILogger<Connection>>();
			cacheBuffer = new byte[1024 * 8];
			qDataPacks = new BlockingCollection<IDataPack>(100);
			ConnectionID = Worker.Builder().NextId();
			context = container.GetService<IContext>();
			context.ConnectionId = ConnectionID;
			//	stopwatch = new Stopwatch();
		}
		public Socket ConnectionClient { get { return client; }  set { client = value; } }
		public IContext Context { get { return context; }  set { context = value; } }
		public long ConnectionID { get { return connectionID; }  set { connectionID = value; } }

		private Socket client;
		private byte[] cacheBuffer;
		private SystemConfiguration sysCfg;
		private IContainer container;
		private IClientManager clientManager;
		private ILogger<Connection> logger;
		private IContext context;
		private IEnumerable<IPipeline> pipelines;
		private bool isConsumption;
		private BlockingCollection<IDataPack> qDataPacks;
		private long connectionID;
		/// <summary>
		/// 
		/// </summary>
		/// <param name="msg"></param>
		public void Send(string msg)
		{
			context.SendUTF8(msg);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="buffer"></param>
		public void Send(byte[] buffer)
		{
			context.Send(buffer);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <exception cref="Exception"></exception>
		public void Receive()
		{
			pipelines = container.GetServiceAll<IPipeline>();

			if (context is Context handleContext)
			{
				
			}
			else
			{
				string msg = "扩展handleContext 请先必须继承HandleContext!";
				logger.LogError(msg);
				throw new Exception(msg);
			}
			//阻塞方法
			Task.Run(async () =>
			{
				while (true)
				{
					//stopwatch.Start();
					try
					{
						if (!client.Connected)
						{
							string msg = "链接已经断开!";
							logger.LogWarning(msg);
							break;
						}
						
						int length =await client.ReceiveAsync(cacheBuffer,SocketFlags.None);
						//	stopwatch.Stop();
						//	logger.LogInformation($"connection 内部{stopwatch.ElapsedMilliseconds}");

						//context.ReceiveBuffer=new byte[context.Length];
						//Array.Copy(cacheBuffer,context.ReceiveBuffer,context.Length);\

						sysCfg.MessageHandle.AnalysisHandle(qDataPacks,cacheBuffer,length);
						

						DispatchDataPack();

						//time+=stopwatch.ElapsedMilliseconds;
                    }
					catch (Exception ex)
					{

						logger.LogError(ex.Message);
						logger.LogError(ex.StackTrace);
						if (ex.InnerException != null)
						{
							logger.LogError(ex.InnerException.Message);
						}
						Dispose();
						break;
					}
				}
			});

		}
		/// <summary>
		/// 
		/// </summary>
		public void Dispose()
		{
			client.Dispose();
			if (clientManager!=null)
			{
				clientManager.RemoveClient(ConnectionID);
			}
			logger.LogInformation($"{ConnectionID}断开链接!");
		}
		/// <summary>
		/// 
		/// </summary>
		private void DispatchDataPack()
		{
			if (isConsumption)
			{
				return;
			}
			isConsumption = true;

			Task.Run(() =>
			{
			while (qDataPacks.Count() > 0)
			{
				context.CurrentPack = qDataPacks.Take();
				if (context.CurrentPack.Complete)
				{
					bool isPipeline = true;
					if (pipelines != null)
						foreach (var pipeline in pipelines)
						{
							if (!pipeline.Process(context))
							{
								isPipeline = false;
								break;
							}
						}
					if (!isPipeline)
					{
						logger.LogWarning("pack 未通过验证,已将该包丢弃!");
						continue;
					}

					try
					{
						sysCfg.MessageHandle.Handle(context);
						sysCfg.MessageHandle.Handled(context);
					}
					catch (Exception ex)
					{
						logger.LogError(ex.Message);
						logger.LogError(ex.StackTrace);
					}

				}
				else
				{
					break;
				}
			}

			});
			isConsumption = false;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="socket"></param>

		public void SetSocket(Socket socket)
		{
			if (ToolSimpleCheck.IsNull(ConnectionClient))
			{
				if (!ToolSimpleCheck.IsNull(socket))
				{
					ConnectionClient = socket;
					context.SetClient(socket);
					Receive();
				}
			}
		}
		/// <summary>
		/// 
		/// </summary>
		/// <typeparam name="TContext"></typeparam>
		/// <returns></returns>

		public TContext GetContext<TContext>() where TContext : class
		{
			if (context is TContext)
			{
				return (TContext)context;
			}
			return null;
		}
		
	}
}
